home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Dev / Oberon / texts / C2Oberon.txt next >
Text File  |  1995-07-02  |  18KB  |  420 lines

  1.      $RCSfile: C2Oberon.txt $
  2.   Description: Hints for converting C code into Oberon
  3.  
  4.    Created by: fjc (Frank Copeland)
  5.     $Revision: 1.2 $
  6.       $Author: fjc $
  7.         $Date: 1994/05/13 19:26:48 $
  8.  
  9.   Copyright © 1994, Frank Copeland.
  10.   This file is part of Oberon-A.
  11.   See Oberon-A.doc for conditions of use and distribution.
  12.   ________________________________________________________________________
  13.  
  14.   [This document is only partly complete (there was more, but DME ate it).
  15.   :-(  It is here because what there is might still be useful.  It will be
  16.   finished for a future release. FJC]
  17.  
  18.   Introduction
  19.   ------------
  20.  
  21.   This document contains advice for translating source code written in C
  22.   into Oberon.  It covers both simple syntax conversion and broader,
  23.   program organisation issues.
  24.  
  25.   C and Oberon both belong to the same tradition of imperative, procedural
  26.   languages that trace their origins back to Algol in the late 1950's.
  27.   They are both general purpose languages and are sufficiently low-level
  28.   that they can be used as system-programming languages (C is more
  29.   conciously directed to this use).  Where they mainly differ is in the
  30.   areas of modularity and type safety; Oberon is stronger in both these
  31.   areas.
  32.  
  33.   In most cases the syntaxes are similar enough to allow a straightforward
  34.   translation from one language to the other.  A text editor with a macro
  35.   facility can help simplify this task.  Difficulties arise when
  36.   encountering constructs common in C which are missing in Oberon, such as
  37.   union types and unsigned integers.  Other, more subtle difficulties may
  38.   arise as a result of C's less strict (often non-existant) type checking.
  39.   Finally, C's approach to modular programming is completely different to
  40.   Oberon's, and may require a complete restructuring of the source code.
  41.  
  42.  
  43.   Simple Data Types
  44.   -----------------
  45.  
  46.   Simple data types are the basic building blocks of all data structures.
  47.   As they are determined by the underlying architecture common to almost
  48.   all modern computers, C and Oberon have a very similer range of basic
  49.   types.  However, while the ANSI C standard specifies minimum sizes and
  50.   ranges for all of these types, Oberon leaves much more up to the
  51.   implementor.  The equivalences given are those for Amiga C compilers and
  52.   the Oberon-A compiler.
  53.  
  54.   The following table helps to explain the equivalences:
  55.  
  56.   ANSI C         Min. Size  Oberon-A
  57.   ------         ---------  --------
  58.  
  59.   char           1 byte     When used to hold ASCII values, the equivalent
  60.                             is CHAR; when used as a small integer, the
  61.                             equivalent is SHORTINT.
  62.   unsigned char  1 byte     When used to hold ASCII values, the equivalent
  63.                             is CHAR; when used as a small integer, the
  64.                             equivalent is BYTE.  For BYTE see below.
  65.   short          2 bytes    INTEGER.
  66.   int            2 bytes    INTEGER or LONGINT.  Some C compilers have
  67.                             16-bit ints, others have 32-bit ints.  For
  68.                             16-bit ints, use INTEGER, otherwise use
  69.                             LONGINT.
  70.   unsigned int   2 bytes    No equivalent.  See below.
  71.   long           4 bytes    LONGINT.
  72.   unsigned long  4 bytes    No equivalent.  See below.
  73.   float          6 digits   REAL.
  74.   double         10 digits  LONGREAL.
  75.   long double    10 digits  LONGREAL.
  76.  
  77.   The BYTE type is strictly limited in Oberon (it is removed in Oberon-2).
  78.   It may be used to represent an unsigned byte-sized value (0-255), but
  79.   the only operation allowed is assignment.  To perform arithmetic on BYTE
  80.   values, you must first assign them to INTEGER variables.
  81.  
  82.   Oberon does not allow for unsigned integers apart from the limited BYTE
  83.   type.  In many cases this is no problem since a signed integer can be
  84.   used instead without problems, although it may be necessary to use a
  85.   larger type (INTEGER instead of SHORTINT, for instance).
  86.  
  87.   The main problem occurs when you must specify a type with the same
  88.   size as the unsigned type; this often occurs when declaring Oberon
  89.   equivalents for the Amiga system data structures.  You cannot use a
  90.   larger type in this case; the system WILL crash if you do.  Often the
  91.   operating system defines unsigned constants to be placed in these
  92.   variables with values that are larger than the maximum for a signed
  93.   integer of that size. These must be converted to negative values using
  94.   this formula:
  95.  
  96.     <constant> - (<max value of unsigned type> + 1).
  97.  
  98.   For example:
  99.  
  100.     An unsigned int constant 0xFFFE or 65534 converts to:
  101.  
  102.       (65534 - (65535 + 1)) = -2.
  103.  
  104.   Often unsigned integers are used as bit fields, which are directly
  105.   equivalent to the Oberon SET type.  An unsigned char bit field is
  106.   equivalent to the SYSTEM.BYTESET type; an unsigned int is equivalent to
  107.   the SYSTEM.WORDSET type; an unsigned long corresponds to the SET type.
  108.   If the exact size of the variable doesn't matter, use the SET type; the
  109.   other two types are unique to the Oberon-A implementation and are not
  110.   portable.
  111.  
  112.   C has no direct equivalent to Oberon's BOOLEAN type, but ints are often
  113.   used for the same purpose.  When they are, a value of zero equates to
  114.   FALSE and any other value equates to TRUE.
  115.  
  116.   Oberon has no equivalent to C's enumerated data types, but they can be
  117.   simulated very easily using integer constants.  For instance:
  118.  
  119.     enum days = { Sun,Mon,Tues,Wed,Thurs,Fri,Sat };
  120.  
  121.   becomes:
  122.  
  123.     CONST
  124.       Sun = 0; Mon = 1; Tues = 2; Wed = 3;
  125.       Thurs = 4; Fri = 5; Sat = 6;
  126.  
  127.  
  128.   Constant values
  129.   ---------------
  130.  
  131.   Character literals in C are defined using single quotes: 'a', 'Z', etc.
  132.   String literals use double quotes: "This is a string".  Oberon uses
  133.   double quotes for both.  This can create an unexpected difficulty.
  134.   Oberon has no way of distinguishing a string literal with a single
  135.   character in it from a character literal except from the context in
  136.   which it is used.  If the compiler does not contain special code to deal
  137.   with the anomaly, perfectly legal code may generate errors.  (Oberon-A
  138.   now handles this anomaly).
  139.  
  140.   String and character literals in C may contain escape sequences such as
  141.   '\n' and "\x5c".  Oberon does not recognise escape sequences (but
  142.   Oberon-A does, as an extension; see OC.doc.)  Character literals in
  143.   Oberon may be expressed as hexadecimal ASCII codes instead: '\n' becomes
  144.   0AX.
  145.  
  146.   In C, any numeric literal starting with "0x" or "0X" is a hexadecimal
  147.   value.  Upper and lower case characters can be used for the hexadecimal
  148.   digits.  Oberon uses an "H" character at the end of the literal to
  149.   indicate a hexadecimal number and hex digits must be in upper case.  A
  150.   number must start with a numeric character, the same as in C.  Example:
  151.   "0xa5d3" becomes "0A5D3H".  Any integer constant in C starting with "0"
  152.   (except for hex constants, obviously) is interpreted as an octal number.
  153.   Oberon has no equivalent for this and the constant must be converted
  154.   into its decimal or hexadecimal equivalent.
  155.  
  156.   A "U" at the end of an integer constant indicates an unsigned number.
  157.   Oberon has no equivalent for this (see above).  An "L" at the end of an
  158.   integer constant indicates that it has a long int type.  This is
  159.   unnecessary in Oberon, which handles all the necessary type conversions
  160.   automagically.
  161.  
  162.   Floating point constants are generally defined the same way in C and
  163.   Oberon, except that an exponent must be indicated with an uppercase "E"
  164.   in Oberon.  C constants usually are of type double; Oberon defaults to
  165.   type REAL.  To specify a LONGREAL constant, Oberon uses a "D" in the
  166.   exponent instead of an "E".  C uses an "L" at the end of a floating
  167.   point constant to indicate it is a long double type; remove this when
  168.   converting to Oberon.
  169.  
  170.   Bit field constants in C are usually defined in one of two ways.  One is
  171.   to use the form: "(1<<bit)" or "(1L<<bit)".  This is equivalent to
  172.   Oberon's: "{bit}".  The other is to use a hex literal, such as:
  173.   "0xC801".  The only way out here is to determine which bits are set in
  174.   the binary representation of the number, remembering that bits are
  175.   numbered starting at 0.  In this case the equivalent is: "{0,11,14,15}".
  176.  
  177.   When used as a boolean, an integer value of 0 is the same as FALSE,
  178.   while any other value is equivalent to TRUE.
  179.  
  180.   Named constants in C are created using the #define macro.  In Oberon
  181.   they are defined in a constant declaration block, which starts with the
  182.   CONST keyword.  Macros definitions are visible until they are undefined
  183.   or until the end of the file.  Oberon constants are visible only in the
  184.   scope in which they are declared, which may be inside a procedure.
  185.  
  186.  
  187.   Operations
  188.   ----------
  189.  
  190.   C has a somewhat richer set of operators than Oberon.  Most of the
  191.   missing operations are provided as standard procedures in the Oberon
  192.   language or by the SYSTEM module supplied with Oberon-A.  Oberon uses a
  193.   much simpler system of operator precedence derived from Pascal.  In
  194.   Oberon you may need to make more use of parentheses to indicate the
  195.   exact order of operations you want.  See the Oberon Report for details
  196.   of Oberon's operator precedence rules.
  197.  
  198.   The following table lists the various operations and their equivalents
  199.   in C and Oberon. n indicates a numeric value, i indicates an integer
  200.   value, r indicates a floating value, b indicates a boolean value, s
  201.   indicates a bit field or set value, v indicates a variable, a and b
  202.   indicate I have run out of ideas:
  203.  
  204.   Operator            C                   Oberon
  205.   ------------------  ------------------  -----------------------
  206.  
  207.   unary minus         n1 = -n2            n1 := -n2
  208.   unary plus          n1 = +n2            n1 := +n2
  209.   logical not         !b                  ~b
  210.   bitwise complement  s1 = ~s2            s1 := -s2
  211.   address             &v                  SYSTEM.ADR (v)
  212.   pointer reference   v1 = *v2            v1 := v2^
  213.   size of             i = sizeof(type)    i := SIZE (type)
  214.                       i = sizeof(v)       i := SIZE (type of v)
  215.                       i = sizeof(expr)    no equivalent
  216.   increment           ++i or i++          INC (i)
  217.   decrement           --i or i--          DEC (i)
  218.   multiplication      n1 = n2 * n3        n1 := n2 * n3
  219.   integer division    i1 = i2 / i3        i1 := i2 DIV i3
  220.   floating division   n1 = n2 / n3        r1 := n2 / n3
  221.   modulus             i1 = i2 % i3        i1 := i2 MOD i3
  222.   addition            n1 = n2 + n3        n1 := n2 + n3
  223.   subtraction         n1 = n2 - n3        n1 := n2 - n3
  224.   shift left          i1 = i2 << i3       i1 := ASH (i2, i3), or
  225.                                           i1 := SYSTEM.LSH (i2, i3)
  226.   shift right         i1 = i2 >> i3       i1 := ASH (i2, -i3), or
  227.                                           i1 := SYSTEM.LSH (i2, -i3)
  228.   greater than        a > b               a > b
  229.   greater or equal    a >= b              a >= b
  230.   less than           a < b               a < b
  231.   less or equal       a <= b              a <= b
  232.   equal               a == b              a = b
  233.   not equal           a != b              a # b
  234.   bitwise AND         i1 = i2 & i3        i1 := SYSTEM.AND (i2, i3)
  235.                       s1 = s2 & s3        s1 := s2 * s3
  236.                       s1 = s2 & ~s3       s1 := s2 - s3
  237.   bitwise OR          i1 = i2 | i3        i1 := SYSTEM.LOR (i2, i3)
  238.                       s1 = s2 | s3        s1 := s2 + s3
  239.   bitwise XOR         i1 = i2 ^ i3        i1 := SYSTEM.XOR (i2, i3)
  240.                       s1 = s2 ^ s3        s1 := s2 / s3
  241.   logical AND         b1 && b2            b1 & b2
  242.   logical OR          b1 || b2            b1 OR b2
  243.   assignment          a = b               a := b
  244.  
  245.   In C, assignment (=) is an operator that may be used in an expression.
  246.   In Oberon, assignment (:=) is a statement. This means that in C you can
  247.   say:
  248.  
  249.     if (c = getchar()) ...
  250.  
  251.   while in Oberon you must use:
  252.  
  253.     c := getchar ();
  254.     IF c # 0X THEN ...
  255.  
  256.   You may have to pay close attention to the C increment and decrement
  257.   operators.  If the operator is placed before the variable, the operation
  258.   is performed before the rest of the expression; if after, the expression
  259.   is performed first.  This determines where the Oberon INC or DEC
  260.   procedure should be placed.
  261.  
  262.   Oberon and C both use short-circuit evaluation when processing boolean
  263.   expressions involving logical AND and logical OR operators.  This means
  264.   that the whole expression may not be evaluated if its result can be
  265.   determined before the end.  For example, in the expression (A & B), if A
  266.   evaluates to FALSE B is never evaluated because it is unnecessary; the
  267.   expression result will be FALSE regardless of the value of B.  When
  268.   translating such expressions, pay close attention to the operator
  269.   precedence rules to make sure that the Oberon expression has the same
  270.   logic as the C expression.
  271.  
  272.   In C you can replace any expression of the form:
  273.  
  274.     A = A <op> B
  275.  
  276.   where <op> is a binary operator, with:
  277.  
  278.     A <op>= B.
  279.  
  280.   In Oberon, you must convert such an expression back into its first form.
  281.   For example:
  282.  
  283.     (C)  A *= B  =>  A := A * B  (Oberon).
  284.  
  285.  
  286.   Block Statement
  287.   ---------------
  288.  
  289.   C has the concept of a block statement, which is a sequence of
  290.   statements enclosed in braces that may be used anywhere in place of a
  291.   single statement.  It takes the form:
  292.  
  293.     { <statement>; <statement>; ... <statement>; }
  294.  
  295.   The closest equivalent in Oberon is the main body of a procedure or
  296.   module, which is a sequence of statements bracketed by BEGIN and END:
  297.  
  298.     BEGIN <statement>; <statement>; ... <statement> END
  299.  
  300.   C also makes use of block statements in if, for and while statements.
  301.   Oberon has its own syntax for these statements; see below.
  302.  
  303.   C block statements can also include variable declarations whose scope is
  304.   limited to the block statement.  In Oberon, such a block must be
  305.   redefined as a local procedure and given a name which is used in place
  306.   of the block statement.  See Subroutines below.
  307.  
  308.   Note also that in Oberon semicolons are statement _seperators_ while in
  309.   C they are _terminators_.  In C, a statement must end with a semicolon;
  310.   in Oberon, a semicolon is only necessary if another statement follows
  311.   it.
  312.  
  313.  
  314.   Conditional Statements
  315.   ----------------------
  316.  
  317.   C and Oberon both have the if/then/else and case conditional statements.
  318.   The different syntaxes for if/then/else are:
  319.  
  320.     ANSI C                            Oberon
  321.  
  322.     if (<expr>)                       IF <bool expr> THEN
  323.       <statement>;                      <statement> {; <statement>}
  324.     [else                             [ELSE
  325.       <statement>;]                     <statement> {; <statement>}]
  326.                                       END
  327.  
  328.   In C, <expr> does not have to be a boolean expression, it only needs to
  329.   evaluate to a zero or non-zero value.  Zero is treated as FALSE,
  330.   non-zero is TRUE.  When translating to Oberon, the expression must be
  331.   converted to a boolean expression.  For example:
  332.  
  333.     if (v) ... (C)  =>  IF v # 0 THEN ...  (Oberon)
  334.  
  335.   In C, the <statement> may be a block statement, in which case the
  336.   semicolon is unnecessary.  In Oberon, the block statement is replaced by
  337.   a sequence of statements, seperated by semicolons.  In both languages
  338.   the else part is optional.  In Oberon the END is mandatory.
  339.  
  340.   In C you may see something like:
  341.  
  342.     if (<expr1>)
  343.       <statement>;
  344.     else if (<expr2>)
  345.       <statement>;
  346.  
  347.   In Oberon, this would be expressed as:
  348.  
  349.     IF <expr1> THEN
  350.       <statement>
  351.     ELSIF <expr2> THEN
  352.       <statement>
  353.     END
  354.  
  355.   The equivalent case statements are:
  356.  
  357.     ANSI C                            Oberon
  358.  
  359.     switch (<expr>) {                 CASE <expr> OF
  360.       case <item> : <statements>        <list> : <statements> |
  361.       case <item> : <statements>        <list> : <statements> |
  362.       ...                               ...
  363.       case <item> : <statements>        <list> : <statements>
  364.       [default    : <statements>]     [ELSE       <statements>]
  365.     }                                 END
  366.  
  367.   In C, only one constant item is allowed per case.  In Oberon each case
  368.   may include a list of constants, including ranges of values.  In C, ALL
  369.   statements after the activated case are executed, unless a break
  370.   statement is encountered.  In Oberon, only the statements associated
  371.   with the activated case are executed.  To illustrate this, the
  372.   following statements are equivalent:
  373.  
  374.     switch (today) {                  CASE today OF
  375.       case Mon :                        Mon .. Fri :
  376.       case Tue :                          StdIO.WriteStr ("go work!")
  377.       case Wed :                        |
  378.       case Thur:                        Sat, Sun :
  379.       case Fri :                          IF today = Sat THEN
  380.         puts ("go work!");                  StdIO.WriteStr ("clean the ");
  381.         break;                              StdIO.WriteStr ("yard and ");
  382.       case Sat :                          END;
  383.         printf                            StdIO.WriteStr ("relax!");
  384.           ( "%s",                         StdIO.WriteLn ();
  385.             "clean the yard and ");   END;
  386.       case Sun :
  387.         puts ("relax!");
  388.     }
  389.  
  390.   Note the use of the "|" character to seperate the cases.
  391.  
  392.   The default part in C and the ELSE part in Oberon are both optional and
  393.   are executed only if none of the other cases are activated.  If no
  394.   default is provided and no case is activated, C simply continues after
  395.   the case statement.  Oberon will cause a run-time error if no cases are
  396.   activated and there is no ELSE.  To get the same behaviour as C, include
  397.   an ELSE with an empty statement (ie - nothing) after it.
  398.  
  399.   Iteration
  400.   ---------
  401.  
  402.   Subroutines
  403.   -----------
  404.  
  405.   Data Structures
  406.   ---------------
  407.  
  408.   Program Structure
  409.   -----------------
  410.  
  411.   Standard Libraries
  412.   ------------------
  413.  
  414.   Other Issues
  415.   ------------
  416.  
  417.   Example programs
  418.   ----------------
  419.  
  420.